/*
 Trabajo Practico 3 Ejercicio 3
 Entrega número: 1

 - Integrantes:
	- Martinez, Guillermo		DNI: 34510461
	- Barrera, Lourdes		DNI: 33306634
	- Reyes, Leandro		DNI: 34213699
	- Rodriguez, Lucas		DNI: 34265017
	- Cortez, Martin		DNI: 30440023
*/

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#define MIN_PISO 10
#define MAX_PISO 30

#define MIN_PINTOR 1
#define MAX_PINTOR 5

#define HAY_PISOS_SIN_PINTAR 0
#define NO_HAY_MAS_PISOS 1

void *pintar_piso (void *id_pintor);

typedef struct{
	pthread_t id;
	int num_pintor;
	int cant_pisos;
	int tiempo_total;
}t_pintor;

typedef struct{
	int id;
	int tiempo;
}t_piso;

int piso = 0;
int cant_pisos, cant_pintores;
t_piso edificio[MAX_PISO];
t_pintor pintores[MAX_PINTOR];

pthread_mutex_t cambio_piso = PTHREAD_MUTEX_INITIALIZER;

int main()
{
	int i;
	FILE * informe;

	printf("Ingrese cantidad de pisos(entre 10 y 30):\n");
	if(scanf("%d",&cant_pisos) != 1){
		fprintf(stderr, "Error al leer el dato de entrada, se aceptan solo enteros\n");
		return 1;
	}

	while(cant_pisos < MIN_PISO || cant_pisos > MAX_PISO){
		printf("Piso invalido, intente de nuevo(entre 10 y 30):\n");
		if(scanf("%d",&cant_pisos) != 1){
			fprintf(stderr, "Error al leer el dato de entrada, se aceptan solo enteros\n");
			return 1;
		}
	}

	printf("Ingrese cantidad de pintores(entre 1 y 5):\n");
	if(scanf("%d",&cant_pintores) != 1){
		fprintf(stderr, "Error al leer el dato de entrada, se aceptan solo enteros\n");
		return 1;
	}

	while(cant_pintores < MIN_PINTOR || cant_pintores > MAX_PINTOR){
		printf("Pintores invalido, intente de nuevo(entre 1 y 5):\n");
		if(scanf("%d",&cant_pintores) != 1){
			fprintf(stderr, "Error al leer el dato de entrada, se aceptan solo enteros\n");
			return 1;
		}
	}

	printf("Cantidad de pisos: %d\n",cant_pisos);
	printf("Cantidad de pintores: %d\n",cant_pintores);
	
	for(i = 0; i < cant_pisos ; i++){
		edificio[i].id = i+1;
		edificio[i].tiempo = (rand()%5)+3;
	}

	for(i = 0; i < cant_pintores ; i++){
		pintores[i].num_pintor = i+1;
		pintores[i].cant_pisos = 0;
		pintores[i].tiempo_total = 0;		
	}

	for(i = 0; i < cant_pintores ; i++){
		if (pthread_create (&pintores[i].id, NULL, pintar_piso, (void*) pintores[i].num_pintor) != 0){
			fprintf(stderr, "Error al crear thread\n");
			return 1;
		}
	}
	
	for(i = 0; i < cant_pintores ; i++)
		pthread_join(pintores[i].id, NULL);
	pthread_mutex_destroy(&cambio_piso);

	informe = fopen ("informe.txt", "w");
	
	printf("\nInforme:\n");
	fprintf(informe,"Informe:\n");
	printf("\tPintor\tCant. pisos pintados\tTiempo total\n");
	fprintf(informe,"\tPintor\tCant. pisos pintados\tTiempo total\n");
	for(i = 0; i < cant_pintores ; i++){
		printf("\t%d\t%d\t\t\t%d\n",pintores[i].num_pintor,pintores[i].cant_pisos,pintores[i].tiempo_total);
		fprintf(informe,"\t%d\t%d\t\t\t%d\n",pintores[i].num_pintor,pintores[i].cant_pisos,pintores[i].tiempo_total);
	}

	fclose(informe);

	return 0;
}

void *pintar_piso (void *id_pintor)
{
	int pintar = HAY_PISOS_SIN_PINTAR, piso_actual, pintor = (int)id_pintor;
	while(pintar == HAY_PISOS_SIN_PINTAR){
		pthread_mutex_lock(&cambio_piso);
			if(piso < cant_pisos){
				piso_actual = piso;
				piso++;
				pintar = HAY_PISOS_SIN_PINTAR;
			}else{
				pintar = NO_HAY_MAS_PISOS;
			}
		pthread_mutex_unlock(&cambio_piso);
		
		if(pintar == HAY_PISOS_SIN_PINTAR){
			printf("El pintor %d pinta el piso %d y va a tardar %d\n", pintor, edificio[piso_actual].id,edificio[piso_actual].tiempo);
			sleep(edificio[piso_actual].tiempo);
			pintores[pintor-1].cant_pisos++;
			pintores[pintor-1].tiempo_total += edificio[piso_actual].tiempo;
		}
	}
	printf("El pintor %d no tiene mas para pintar\n", pintor);
	pthread_exit(NULL);
}